home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / inventor / soundspheres / PlayClass.c++ < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  24.0 KB  |  1,063 lines

  1. /*
  2.  * Copyright (C) 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. #include <stdio.h>
  18. #include <fcntl.h>
  19. #include <errno.h>
  20. #include <sys/types.h>
  21. #include <sys/stat.h>
  22. #include <sys/prctl.h>
  23. #include <sys/wait.h>
  24. #include <malloc.h>
  25. #include <math.h>
  26. #include <string.h>
  27. #include <getopt.h>
  28. #include <CC/osfcn.h>
  29. #include <signal.h>
  30. #include <invent.h>
  31.  
  32. #include "PlayClass.h"
  33.  
  34. static void quietAFerror(long, const char *);
  35. static void quietALerror(long, const char *, ...);
  36.  
  37.  
  38. /*
  39.  * local defines
  40.  */
  41. #ifndef FALSE
  42. #define FALSE (0)
  43. #define TRUE (!FALSE)
  44. #endif
  45. #ifndef ABS
  46. #define ABS(a)        ((a)>0.0?(a):-(a))
  47. #endif
  48. #ifndef MIN
  49. #define    MIN(a, b)    ((a)<(b)?(a):(b))
  50. #endif
  51. #ifndef MAX
  52. #define    MAX(a, b)    ((a)>(b)?(a):(b))
  53. #endif
  54. #define    RANGE(a, b1, b2)            \
  55.                         \
  56.         ((b1)<(b2)?                \
  57.          ((a)<(b1)?                \
  58.           (b1):                \
  59.           ((a)>(b2)?            \
  60.                (b2):(a))):        \
  61.          ((a)<(b2)?                \
  62.           (b2):                \
  63.           ((a)>(b1)?            \
  64.                (b1):(a))))
  65.  
  66. #ifndef INTERP
  67. #define INTERP(x1, x2, a) ((a)*(x2)+(1.0-(a))*(x1))
  68. #endif
  69.  
  70.  
  71. PlayClass::PlayClass(char *mname)
  72. {
  73.     myname = mname;
  74.     rude    = TRUE;
  75.     quiet  = FALSE;
  76.     timed = FALSE;
  77.     verbose = FALSE;
  78.     NoDone = FALSE;
  79. #ifdef DEBUG
  80.     verbose = TRUE;
  81. #endif
  82.     caught_sigint = FALSE;
  83.     paused = FALSE;
  84.     filename = NULL;
  85.     doneCallback = NULL;
  86.     loop = FALSE;
  87.     fading_in = FALSE;
  88.     fading_out = FALSE;
  89.     in_time = 0.0;
  90.     out_time = 0.0;
  91.     fade_level = 0.0;
  92.     max_level = 1.0;
  93.     isLive = FALSE;
  94.     isDone = TRUE;
  95.     sproced = FALSE;
  96.  
  97.     useDistance = FALSE;
  98.     emitX = emitY = emitZ = 0.0;
  99.     recX = recY = recZ = 0.0;
  100.     distanceChanged = TRUE;
  101.     distanceFactor = 1.0;
  102.  
  103.     signal(SIGCLD,SIG_IGN); /* ensure no zombie child processes */
  104. }
  105.  
  106.  
  107. /*
  108.  * attenuatesamps
  109.  *
  110.  *        tristram, 1993
  111.  *              goldsmith, 1993, 1994
  112.  *
  113.  * put a ramp on a buffer of samples, starting at the current fade_level
  114.  * at a slope of 1 / fade_time.
  115.  *
  116.  * mode = 0 ==> fade in
  117.  * mode = 1 ==> fade out
  118.  * mode = 2 ==> don't adjust fade_level (just use max_level)
  119.  *
  120.  * this function has the side effect of setting fade_level
  121.  *
  122.  */
  123.  
  124. void
  125. PlayClass::attenuatesamps( void * sampbuf, long sampsize, long nsamps,
  126.                double secs_per_buf,
  127.            double max_level,
  128.            double * fade_level,
  129.            double fade_time,
  130.            int mode ) {
  131.  
  132.   int i;
  133.   double distance; 
  134.   double diffX, diffY, diffZ;
  135.  
  136.   if (useDistance && distanceChanged) {
  137. #ifdef DEBUG
  138.     fprintf(stderr, "computing new distance\n");
  139. #endif    
  140.     diffX = emitX - recX;
  141.     diffY = emitY - recY;
  142.     diffZ = emitZ - recZ;
  143.     distance = diffX * diffX + diffY * diffY + diffZ * diffZ;
  144.     if (distance < 1.0) distance = 1.0;
  145.     distanceFactor = 1.0 / distance;
  146.     distanceChanged = FALSE;
  147.   } else {
  148.   }
  149.  
  150. #ifdef DEBUG
  151. fprintf(stderr, "attenuating max_level = %f, fade_level = %f, fade_time = %f distanceFactor = %f\n", max_level, *fade_level, fade_time, distanceFactor);
  152. #endif
  153.  
  154.   if ( verbose ) printf( "fade_level = %f\n", *fade_level );
  155.  
  156.   if (( mode != 2 ) && ( fade_time == 0.0 )) {
  157.     if ( *fade_level == 0.0 ) *fade_level = 1.0;
  158.     else              *fade_level = 0.0;
  159.     return;
  160.   }
  161.  
  162.   for ( i = 0; i < nsamps; i++ ) {
  163.     switch ( sampsize ) {
  164.     case AL_SAMPLE_8:
  165.       ((char *)sampbuf)[ i ] *= max_level * *fade_level * distanceFactor;
  166.       break;
  167.     case AL_SAMPLE_16:
  168.       ((short *)sampbuf)[ i ] *= max_level * *fade_level * distanceFactor;
  169.       break;
  170.     case AL_SAMPLE_24:
  171.       ((long *)sampbuf)[ i ] *= max_level * *fade_level * distanceFactor;
  172.       break;
  173.     }
  174.  
  175.     if ( mode != 2 ) {
  176.       if ( fade_time == 0.0 ) {
  177.     if ( mode == 0 ) { /* fading in */
  178.       *fade_level = 1.0;
  179.     } else { /* fading  out */
  180.       *fade_level = 0.0;
  181.     }
  182.       } else {
  183.     *fade_level += ( mode == 0 ? 1.0 : -1.0 )
  184.       * secs_per_buf / (fade_time * nsamps);
  185.     *fade_level = RANGE( *fade_level, 0.0, 1.0 );
  186.       }
  187.     }
  188.   }
  189. }
  190.  
  191.  
  192.  
  193. int PlayClass::beginPlaying()
  194. {
  195. #ifdef DEBUG
  196.   fprintf(stderr, "beginPlaying()\n");
  197. #endif
  198.     AFfilehandle audio_file;
  199.     ALconfig audio_port_config;
  200.     ALport audio_port;
  201.     int errseen = 0;
  202.     int result;
  203.  
  204. #ifdef DEBUG
  205.   fprintf(stderr, "checkpoint 1()\n");
  206. #endif
  207.  
  208.   if (isDone) isDone = FALSE;
  209.   else return -1;
  210.  
  211.   isLive = TRUE;
  212.   fading_in = FALSE;
  213.   fading_out = FALSE;
  214.   fade_level = 0.0;
  215.   caught_sigint = FALSE;
  216.  
  217.   max_level = RANGE( max_level, 0.0, 1.0 );
  218.   if (in_time == 0.0) fade_level = 1.0;
  219.  
  220. #ifdef DEBUG
  221.   fprintf(stderr, "new max_level is %f\n", max_level);
  222. #endif
  223.  
  224.     if ((fd = open(filename, O_RDONLY)) < 0)
  225.       {
  226.       if (!quiet)
  227.         {
  228.                 fprintf(stderr, "%s: failed to open file '%s' %s\n",
  229.                      myname, filename, strerror(errno));
  230.             }
  231.             errseen = 1;
  232.       }
  233.     /*
  234.      * test the file descriptor to see whether we can attach an audio
  235.      *    file handle to it
  236.      */
  237.     else if (AFidentifyfd(fd) < 0) 
  238.       {
  239.       if (!quiet)
  240.         {
  241.                 fprintf(stderr,"%s: '%s' not an AIFF-C or AIFF file\n",
  242.                      myname, filename);
  243.             }
  244.             errseen = 1;
  245.       }
  246.     /*
  247.      * attach an audio file handle to the file descriptor
  248.      */
  249.     else if ((audio_file = AFopenfd(fd, "r", AF_NULL_FILESETUP)) 
  250.          == AF_NULL_FILEHANDLE)
  251.       {
  252.       if (!quiet)
  253.             {
  254.                 fprintf(stderr, "%s: failed to open file '%s'\n", 
  255.             myname, filename);
  256.             }
  257.       errseen = 1;
  258.       }
  259.     else 
  260.       {
  261.       result = init_audio(audio_file, &audio_port, &audio_port_config);
  262. #ifdef DEBUG
  263.   fprintf(stderr, "result = %d\n", result);
  264. #endif
  265.       if (result != -1)
  266.             {
  267. #ifdef DEBUG
  268.   fprintf(stderr, "playing audio", result);
  269. #endif
  270.                 play_audio_samps(audio_file, audio_port, audio_port_config);
  271.             } else {
  272.         errseen = 1;
  273.         }
  274.       AFclosefile(audio_file);
  275. #ifdef DEBUG
  276.   fprintf(stderr, "freeing config... ");
  277. #endif
  278.       ALfreeconfig(audio_port_config);
  279. #ifdef DEBUG
  280.   fprintf(stderr, "done\n");
  281. #endif
  282.       if (result != -1) 
  283.             {
  284.             ALcloseport(audio_port);
  285.             }
  286.       free(sampbuf);
  287.       }
  288.     if (errseen) {
  289. #ifdef DEBUG
  290.       fprintf(stderr, "error! returning -1\n");
  291. #endif
  292.     isDone = 1;
  293.         if (sproced) exit(0);
  294.     return -1;
  295.       }
  296.     else {
  297. #ifdef DEBUG
  298.     fprintf(stderr, "done\n");
  299. #endif
  300.     if (doneCallback) {
  301. #ifdef DEBUG
  302.         fprintf(stderr, "calling doneCallback\n");
  303. #endif
  304.         doneCallback(userData, this);
  305.     }
  306.     isDone = 1;
  307.     if (sproced) {
  308. #ifdef DEBUG
  309.     fprintf(stderr, "exiting zero");
  310. #endif
  311.     exit(0);
  312.     }
  313. #ifdef DEBUG
  314.     fprintf(stderr, "after exit(0)");
  315. #endif
  316.     return 1;
  317.     }
  318. }
  319.  
  320. /*
  321.  * initialize audio port and global state of IRIS Audio Processor
  322.  */
  323. int 
  324. PlayClass::init_audio(AFfilehandle audio_file, ALport *audio_port,
  325.               ALconfig *ap_config)
  326. {
  327. #ifdef DEBUG
  328.   fprintf(stderr, "init_audio(...)\n");
  329. #endif
  330. //    long pvbuf[4];
  331.     long pvbuf[2];
  332.     long audio_rate;
  333.     long samp_type;
  334.     long samp_wordsize;    
  335.     long vers;
  336.  
  337.     samps_per_frame   = (int) AFgetchannels(audio_file, AF_DEFAULT_TRACK);
  338.     file_rate         = AFgetrate(audio_file, AF_DEFAULT_TRACK);
  339.     compression       = AFgetcompression(audio_file, AF_DEFAULT_TRACK);
  340.     filefmt           = AFgetfilefmt(audio_file, &vers);
  341.  
  342.     AFgetsampfmt(audio_file, AF_DEFAULT_TRACK, &samp_type, &bits_per_samp);
  343.  
  344.     /*
  345.      * need to determine whether audio is in use. if not, then we
  346.      * can just go ahead and be "rude."
  347.      */
  348.     pvbuf[0] = AL_OUTPUT_COUNT;
  349. //    pvbuf[2] = AL_MONITOR_CTL;
  350. //    ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 4);
  351.     ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  352.  
  353. //    if ((pvbuf[1] == 0) && (pvbuf[3] == AL_MONITOR_OFF)) {
  354.     if (pvbuf[1] == 0) {
  355.         rude = 1;
  356.     }
  357.     
  358.     /* 
  359.      * decide on output rate for the audio hardware
  360.      */
  361.     switch((long)file_rate)
  362.     {
  363.         case 48000: audio_rate = AL_RATE_48000; frames_per_sec = 48000; break;
  364.         case 44100: audio_rate = AL_RATE_44100; frames_per_sec = 44100; break;
  365.         case 32000: audio_rate = AL_RATE_32000; frames_per_sec = 32000; break;
  366.         case 22050: audio_rate = AL_RATE_22050; frames_per_sec = 22050; break;
  367.         case 16000: audio_rate = AL_RATE_16000; frames_per_sec = 16000; break;
  368.         case 11025: audio_rate = AL_RATE_11025; frames_per_sec = 11025; break;
  369.         case 8000: audio_rate = AL_RATE_8000; frames_per_sec = 8000; break;
  370.         default:
  371.             if (!quiet)
  372.             {
  373.                 fprintf(stderr, "%s: can't play data at sample rate %f\n",
  374.                   myname, file_rate);
  375.             }
  376.             frames_per_sec = 44100; /* pick some arbitrary rate */
  377.             audio_rate = AL_RATE_44100;
  378.     }
  379.     /*
  380.      * determine the current output rate
  381.      */
  382.     pvbuf[0] = AL_OUTPUT_RATE;
  383.     ALgetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  384.     /*
  385.      * if the rates are the same, all is well. if not, then we need to proceed
  386.      * in a either a "rude" or "polite" manner.
  387.      */
  388.     if (pvbuf[1] != audio_rate)
  389.     {
  390.     if (rude)
  391.     {
  392.         pvbuf[1] = audio_rate;
  393.         ALsetparams(AL_DEFAULT_DEVICE, pvbuf, 2);
  394.     }
  395.     else /*polite*/
  396.     {
  397.         double tmp_rate;
  398.         
  399.             if (!quiet)
  400.             {
  401.             switch (pvbuf[1])
  402.                 {
  403.                     case AL_RATE_48000: tmp_rate = 48000; break;
  404.                     case AL_RATE_44100: tmp_rate = 44100; break;
  405.                     case AL_RATE_32000: tmp_rate = 32000; break;
  406.                     case AL_RATE_22050: tmp_rate = 22050; break;
  407.                     case AL_RATE_16000: tmp_rate = 16000; break;
  408.                     case AL_RATE_11025: tmp_rate = 11025; break;
  409.                     case AL_RATE_8000:  tmp_rate = 8000;  break;
  410.                  }
  411.                  fprintf(stderr,
  412.         "%s: '%s': adjust system output rate (currently %6.1f Hz)\n",
  413.                     myname, filename, tmp_rate);
  414.  
  415.             }
  416.         }
  417.     }
  418.     
  419.  
  420.     /*
  421.      * decide what size blocks of samples we should read from the
  422.      * input file and pass to ALwritesamps
  423.      */
  424.     if (bits_per_samp <= 8)
  425.     {
  426.        bytes_per_samp = 1;
  427.        samp_wordsize  = AL_SAMPLE_8;
  428.     }
  429.     else if (bits_per_samp <= 16)
  430.     {
  431.        bytes_per_samp = 2;
  432.        samp_wordsize  = AL_SAMPLE_16;
  433.     }
  434.     else if (bits_per_samp <= 24)
  435.     {
  436.        bytes_per_samp = 4;
  437.        samp_wordsize  = AL_SAMPLE_24;
  438.     }
  439.     else
  440.     {
  441.         if (!quiet)
  442.         { 
  443.             fprintf(stderr, "%s: %s: error can't play %d bit samples\n",
  444.                 myname, filename, bits_per_samp);
  445.         }
  446.         return(-1);
  447.     }
  448.  
  449.     if ((samps_per_frame != 1) && (samps_per_frame!= 2))
  450.     {
  451.        if (!quiet)
  452.        {
  453.           fprintf(stderr, "%s: %s: error can't play %d channel sample data\n",
  454.              myname, filename, samps_per_frame);
  455.        }
  456.        return(-1);
  457.     }
  458.  
  459.     /*
  460.      * make the buffer large enough to hold 1/2 sec of audio frames
  461.      * we add one to frames_per_sec before we divide in order to
  462.      * correctly handle the 11025 case
  463.      */
  464.     secs_per_frame = 1.0 / ((double)frames_per_sec);
  465. //    frames_per_buf = (frames_per_sec+1)/2;
  466.   /* ok, I changed this so that now Im holding 1/4 sec of audio frames */
  467.     frames_per_buf = (int) (frames_per_sec+15)/20;
  468.  
  469.     samps_per_buf = frames_per_buf * samps_per_frame;
  470.     bytes_per_buf = samps_per_buf * bytes_per_samp;
  471.     secs_per_buf  = secs_per_frame * frames_per_buf;
  472.  
  473.     sampbuf = (char *) malloc(bytes_per_buf);
  474.  
  475.     /*
  476.      * configure and open audio port
  477.      */
  478.     *ap_config = ALnewconfig();
  479.     ALsetwidth(*ap_config, samp_wordsize);
  480.     ALsetchannels(*ap_config, samps_per_frame);
  481.  
  482.     /*
  483.      * make the ring buffer large enough to hold 1 sec of audio samples
  484.      */
  485.     ALsetqueuesize(*ap_config, samps_per_buf*2);
  486.     *audio_port = ALopenport(myname, "w", *ap_config);
  487.  
  488.     if (*audio_port != NULL) {
  489.     return (1);
  490.     }
  491.     else {
  492.     return (-1);
  493.     }
  494.  
  495. }
  496.  
  497.  
  498. /*
  499.  * play audio sample data through the output port
  500.  */
  501. int
  502. PlayClass::play_audio_samps(AFfilehandle audio_file, ALport audio_port,
  503.                 ALconfig ap_config)
  504. {
  505. #ifdef DEBUG
  506.   fprintf(stderr, "play_audio_samps(...)\n");
  507. #endif
  508.     int num_bufs;
  509.     int leftover_bytes;
  510.     int leftover_samps;
  511.     int leftover_frames;
  512.     long samp_wordsize;
  513.     int samp_count;
  514.     int frame_count;
  515.     double sec_count;
  516.     int i;
  517.     int samples_read;
  518.     int frames_read;
  519.     int done;
  520.     int shortread;
  521.     int total_frames;    
  522.     int total_samps;
  523.     int total_samp_bytes;
  524.  
  525.     char compressionname[10];
  526.     float fileplayingtime;
  527.  
  528.     sec_count = 0.0;
  529.  
  530.     /*
  531.      * figure out how many reads we have to do
  532.      */
  533.     total_frames    =  (int) AFgetframecnt(audio_file, AF_DEFAULT_TRACK);
  534.     total_samps      =  total_frames * samps_per_frame;
  535.     total_samp_bytes =  total_samps * bytes_per_samp;
  536.     num_bufs         = total_samp_bytes / bytes_per_buf;
  537.     leftover_bytes   = total_samp_bytes % bytes_per_buf;
  538.     leftover_samps   = leftover_bytes / bytes_per_samp;
  539.     leftover_frames  = leftover_samps / samps_per_frame;
  540.  
  541.     samp_wordsize = ALgetwidth(ap_config);
  542.  
  543.     if (!quiet)
  544.     {
  545.         fileplayingtime = (float)total_frames / (float)frames_per_sec;
  546.         switch (compression)
  547.         {
  548.             default:
  549.             case AF_COMPRESSION_NONE: 
  550.                     strcpy(compressionname, "");
  551.                     break;
  552.             case AF_COMPRESSION_G722:
  553.                     strcpy(compressionname, "G.722 -->");
  554.                     break;
  555.             case AF_COMPRESSION_G711_ALAW:
  556.                     strcpy(compressionname, "A-law -->");
  557.                     break;
  558.             case AF_COMPRESSION_G711_ULAW:
  559.                     strcpy(compressionname, "u-law -->");
  560.                     break;
  561.         }
  562.     }
  563.     if (verbose) 
  564.     {
  565.     printf("%s: '%s' %6.3f sec %7.1f Hz %6s %s %d-bit %s\n",
  566.            myname,
  567.            filename,
  568.            fileplayingtime,
  569.            file_rate,
  570.            samps_per_frame == 1 ? "mono" : "stereo",
  571.            compressionname,
  572.            bits_per_samp,
  573.            filefmt == AF_FILE_AIFFC ? "AIFF-C" : "AIFF"
  574.        );
  575.         printf( "        total sample frames       = %d (%d bytes)\n",
  576.                     total_frames, total_samp_bytes);
  577.         printf( "        play data using blocksize = %d sample frames\n",
  578.                     frames_per_buf);
  579.         printf( "        total blocks              = %d (%d extra frames)\n",
  580.                     num_bufs, leftover_frames); 
  581.     }
  582.  
  583.     sec_count = 0.0;
  584.  top:
  585.  
  586.     /*
  587.      * move the fileptr to the beginning of the sample data
  588.      */
  589.     AFseekframe(audio_file, AF_DEFAULT_TRACK, 0);
  590.  
  591.     /*
  592.      * note that there may be some pad bytes following the valid samples -
  593.      * for example, the sample data area may be padded so that the valid 
  594.      * samples begin on a block boundary and the sample area ends on a block
  595.      * boundary (where blocksize is specified by the user)
  596.      */
  597.     done        = 0;
  598.     shortread   = 0;
  599.     samp_count  = 0;
  600.     frame_count = 0; 
  601. //    sec_count   = 0.0;
  602.  
  603.     for (i=0; i<num_bufs; i++)
  604.     {
  605.         samp_count  += samps_per_buf;
  606.         frame_count += frames_per_buf;
  607.         sec_count   += secs_per_buf;
  608.  
  609.         if (verbose) 
  610.         {
  611.             printf("        %d sample frames  %6.3f secs\n",
  612.                 frame_count, sec_count); 
  613.         }
  614.         if ((frames_read 
  615.             = (int) AFreadframes(audio_file, AF_DEFAULT_TRACK, 
  616.                           sampbuf, frames_per_buf)) < frames_per_buf)
  617.         {
  618.             if (!quiet)
  619.             {
  620.                 fprintf(stderr, 
  621.          "%s: warning short read for %s: expected %d frames, got %d frames\n",
  622.                         myname, filename, frames_per_buf, frames_read);
  623.             }
  624. //            done++;
  625.         shortread++;
  626.         }
  627.         samples_read = frames_read * samps_per_frame;
  628.  
  629.     if ( timed && ( sec_count - in_time > play_time )) {
  630.       fading_in = FALSE;
  631.       fading_out = TRUE;
  632.     }
  633.  
  634.     if ( !timed && !loop && ( sec_count > (double) fileplayingtime - out_time)) {
  635. #ifdef DEBUG
  636.   fprintf(stderr, "fading out\n");
  637. #endif
  638.       fading_in = FALSE;
  639.       fading_out = TRUE;
  640.     }
  641.        
  642.     if (fading_in) {
  643.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  644.              max_level, &fade_level, in_time, 0 );
  645.       if ( fade_level >= 1.0 ) fading_in = FALSE;
  646.     }
  647.     if (fading_out) {
  648.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  649.              max_level, &fade_level, out_time, 1 );
  650.       if ( fade_level <= 0.0 ) {
  651. #ifdef DEBUG
  652.   fprintf(stderr, "fade level is less than zero, exiting \n");
  653. #endif
  654.         fading_out = FALSE;
  655.         done = TRUE;
  656.       }
  657.     }
  658.     if ( ! ( fading_out || fading_in ) &&
  659.          (( max_level != 1.0 ) || useDistance))
  660.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  661.              max_level, &fade_level, out_time, 2 );
  662.  
  663.  
  664.         ALwritesamps(audio_port, sampbuf, samples_read);
  665.  
  666.     if (caught_sigint) {
  667.         done++;
  668. #ifdef DEBUG
  669.         fprintf(stderr, "caught_sigint\n");
  670. #endif
  671.     }
  672.  
  673. /*   THIS DOES NOT WORK, MAYBE SOMEDAY
  674.     if (paused) {
  675.         if (sproced) {
  676. #ifdef DEBUG
  677.   fprintf(stderr, "pausing... ");
  678. #endif
  679.         while(paused) {}
  680. #ifdef DEBUG
  681.   fprintf(stderr, "done\n");
  682. #endif
  683.         }
  684.     }
  685. */
  686.  
  687.  
  688.         if (shortread)
  689.         {
  690.           /*
  691.            * allow the audio buffer to drain
  692.            */
  693.             while(ALgetfilled(audio_port) > 81920) {
  694.                sginap(1);
  695.             }
  696.         if (loop) 
  697.           goto top;
  698.         else
  699.           done = 1;
  700.  
  701.     }
  702.     if (done) {
  703.         while(ALgetfilled(audio_port) > 0) {
  704.         sginap(1);
  705.         }
  706.         sginap(10);
  707.         return(0);
  708.     }
  709.     }
  710.  
  711.     /*
  712.      * play the leftovers
  713.      */
  714.     samp_count  += leftover_samps;
  715.     frame_count += leftover_frames;
  716.     sec_count   += ((double)leftover_frames) * secs_per_frame;
  717.     if (verbose && leftover_samps>0) 
  718.     {
  719.         printf("        %d sample frames  %6.3f secs\n",
  720.                frame_count, sec_count); 
  721.     }
  722.     if ((frames_read = 
  723.        (int) AFreadframes(audio_file, AF_DEFAULT_TRACK, sampbuf, 
  724.                                         leftover_frames)) < leftover_frames)
  725.     {
  726.         if (!quiet)
  727.         { 
  728.             fprintf(stderr, 
  729.          "%s: warning short read for %s: expected %d frames, got %d frames\n",
  730.                     myname, filename, leftover_frames, frames_read);
  731.         }
  732.  
  733.     }
  734.     samples_read = frames_read * samps_per_frame;
  735.  
  736.  
  737.     if ( timed && ( sec_count - in_time > play_time )) {
  738.       fading_in = FALSE;
  739.       fading_out = TRUE;
  740.     }
  741.  
  742.     if ( !timed && !loop && ( sec_count > (double) fileplayingtime - out_time)) {
  743. #ifdef DEBUG
  744.   fprintf(stderr, "fading out 2\n");
  745. #endif
  746.       fading_in = FALSE;
  747.       fading_out = TRUE;
  748.     }
  749.  
  750.     if (fading_in) {
  751.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  752.              max_level, &fade_level, in_time, 0 );
  753.       if ( fade_level >= 1.0 ) fading_in = FALSE;
  754.     }
  755.     if (fading_out) {
  756.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  757.              max_level, &fade_level, out_time, 1 );
  758.       if ( fade_level <= 0.0 ) {
  759.     fading_out = FALSE;
  760.     done = TRUE;
  761.       }
  762.     }
  763.     if ( ! ( fading_out || fading_in ) && (( max_level != 1.0 ) ||
  764.          useDistance))
  765.       attenuatesamps( sampbuf, samp_wordsize, samples_read, secs_per_buf,
  766.              max_level, &fade_level, out_time, 2 );
  767.  
  768.     ALwritesamps(audio_port, sampbuf, samples_read);
  769.  
  770.     /*
  771.      * allow the audio buffer to drain
  772.      */
  773.     while(ALgetfilled(audio_port) > 81920) {
  774.        sginap(1);
  775.     }
  776.     if (loop) goto top;
  777.  
  778.     while(ALgetfilled(audio_port) > 0) {
  779.        sginap(1);
  780.     }
  781.     sginap(10);
  782.     return(0);
  783. }
  784.  
  785. void
  786. PlayClass::setVerbose(int i)
  787. {
  788.     verbose = i;
  789. }
  790.  
  791. void
  792. PlayClass::setFilename(char *fname)
  793. {
  794.     filename = fname;
  795. }
  796.  
  797. void
  798. PlayClass::setQuiet(int i)
  799. {
  800.     quiet = i;
  801. }
  802.  
  803. void
  804. PlayClass::setRude(int i)
  805. {
  806.     rude = i;
  807. }
  808.  
  809. void
  810. PlayClass::setLoop(short i)
  811. {
  812.     loop = i;
  813. }
  814.  
  815. void
  816. PlayClass::setTime(double secs)
  817. {
  818.     play_time = secs;
  819.     timed = TRUE;
  820. }
  821.  
  822. void
  823. PlayClass::setInTime(double secs)
  824. {
  825.     if (secs == 0.0) {
  826.     fading_in = FALSE;
  827.     in_time = 0.0;
  828.     } else {
  829.     fading_in = TRUE;
  830.     in_time = secs;
  831.     }
  832.     
  833. }
  834.  
  835. void
  836. PlayClass::setOutTime(double secs)
  837. {
  838.     out_time = secs;
  839. }
  840.  
  841.  
  842. void PlayClass::setMaxOutputLevel(double lvl)
  843. {
  844.     max_level = lvl;
  845. }
  846.  
  847. void PlayClass::setNoDone(short nd)
  848. {
  849.     NoDone = nd;
  850. }
  851.  
  852. short PlayClass::getIsLive()
  853. {
  854.     return isLive;
  855. }
  856.  
  857. short PlayClass::donep()
  858. {
  859.     if (NoDone) return FALSE;
  860.     else return isDone;
  861. }
  862.  
  863. void
  864. PlayClass::setCallback(PlayClassCB *Callback, void *d)
  865. {
  866. #ifdef DEBUG
  867.     fprintf(stderr, "setCallback\n");
  868. #endif
  869.     doneCallback = Callback;
  870.     userData  = d;
  871. }
  872.  
  873.  
  874. int
  875. PlayClass::start()
  876. {
  877.  
  878.     short hasAudio = FALSE;
  879.   
  880.     if (filename == NULL) return -1;
  881.  
  882.     inventory_t* invry_p;
  883.  
  884.     while((invry_p = getinvent()) != 0) {
  885.     if (invry_p->inv_class == INV_AUDIO) {
  886.       hasAudio = TRUE;
  887.       break;
  888.         }
  889.     }
  890.  
  891.     setinvent();
  892.     endinvent();
  893.  
  894.  
  895.     if (!hasAudio) return -1;
  896.     // this is a quick check to see if there is an audio port available
  897.     ALconfig conf = ALnewconfig();
  898.     ALport   prt;
  899.     if ( (prt = ALopenport( "noname", "w", conf )) != NULL ) {
  900.         // Close the audio port. We only opened it to check 
  901.         // if it was available.
  902.         ALcloseport(prt);
  903.     } else {
  904. #ifdef DEBUG
  905.   fprintf(stderr, "all ports in use, I wasn't able to open a new one\n");
  906. #endif
  907.             audio_pid = -1;
  908.         return -1;
  909.     }
  910.       
  911. #ifdef DEBUG
  912.     fprintf(stderr, "start() filename = %s\n", filename);
  913. #endif
  914.    /*
  915.     *    Use the sproc(2) call to create an audio thread. The audio
  916.     *    thread begins execution at the do_audio entry point. The 
  917.     *    second argument to sproc, PR_SALL, allows the two processes
  918.     *    to share all attributes. See the manual page for the sproc(2)
  919.     *    system call for more details.
  920.     */
  921.     audio_pid =
  922.       sproc((void (*)(void *))&PlayClass::go, PR_SALL, (void *) this);
  923.    if (audio_pid < 0)
  924.    {
  925.        fprintf(stderr, "unable to create audio thread...aborting.\n");
  926.        return -1;
  927.    }
  928. #ifdef DEBUG
  929.      fprintf(stderr, "returning 1, audio_pid = %d\n", audio_pid);
  930. #endif
  931.    sproced = TRUE;
  932.    return 1;
  933.  
  934. }
  935.  
  936. void PlayClass::go(void *obj)
  937. {
  938. #ifdef DEBUG
  939.     fprintf(stderr, "go()\n");
  940. #endif
  941.     PlayClass *objPtr = (PlayClass *) obj;
  942.  
  943.     objPtr->beginPlaying();
  944. #ifdef DEBUG
  945.     fprintf(stderr, "return from beginPlaying()\n");
  946.     fprintf(stderr, "process = %d\n", objPtr->audio_pid);
  947. #endif
  948. }
  949.  
  950. void
  951. PlayClass::fadeOut()
  952. {
  953. #ifdef DEBUG
  954.   fprintf(stderr, "PlayClass::fadeOut()\n");
  955. #endif
  956.     if (out_time > 0.0) {
  957.     fading_out = TRUE;
  958.     fading_in = FALSE;
  959.     return;
  960.     } else {
  961.     stop();
  962.     }
  963. }
  964.  
  965. void
  966. PlayClass::pause()
  967. {
  968.     paused = TRUE;
  969. }
  970.  
  971. void
  972. PlayClass::unpause()
  973. {
  974.     paused = FALSE;
  975. }
  976.  
  977. void
  978. PlayClass::stop()
  979. {
  980.  
  981. #ifdef DEBUG
  982.       fprintf(stderr, "stop()\n");
  983. #endif
  984.       caught_sigint = 1;
  985. #ifdef DEBUG
  986.       fprintf(stderr, "waiting...");
  987. #endif
  988. //      pid_t pid;
  989. //      int status;
  990. //      pid = wait(&status);
  991.     if (audio_pid != -1) {
  992.     union wait waitStatus;
  993.     (void) waitpid(audio_pid, (int *) (&waitStatus), 0);
  994.     }
  995.  
  996. #ifdef DEBUG
  997.       fprintf(stderr, "done.\n");
  998. #endif
  999.     caught_sigint = 0;
  1000.     isLive = FALSE;
  1001. }
  1002.  
  1003.  
  1004.  
  1005. void PlayClass::setUseDistance(short useP)
  1006. {
  1007.     useDistance = useP;
  1008.     if (useP) {
  1009.         distanceChanged = TRUE;
  1010.     } else {
  1011.         distanceFactor = 1.0;
  1012.     }
  1013. }
  1014.  
  1015. short PlayClass::getUseDistance()
  1016. {
  1017.     return useDistance;
  1018. }
  1019.  
  1020. void PlayClass::setEmitterPosition(double x, double y, double z)
  1021. {
  1022. #ifdef DEBUG
  1023.     fprintf(stderr, "new emitter pos: %f %f %f\n", x,y,z);
  1024. #endif
  1025.     emitX = x;
  1026.     emitY = y;
  1027.     emitZ = z;
  1028.     distanceChanged = TRUE;
  1029. }
  1030.  
  1031. void PlayClass::setReceiverPosition(double x, double y, double z)
  1032. {
  1033. #ifdef DEBUG
  1034.     fprintf(stderr, "new receiver pos: %f %f %f\n", x,y,z);
  1035. #endif
  1036.     recX = x;
  1037.     recY = y;
  1038.     recZ = z;
  1039.     distanceChanged = TRUE;
  1040. }
  1041.  
  1042.  
  1043.  
  1044. /*
  1045.  * application-defined silent error reporting routine
  1046.  * for Audio Library
  1047.  */
  1048. static void
  1049. //quietALerror(long code, const char *desc, ...)
  1050. quietALerror(long , const char *, ...)
  1051. {
  1052. }
  1053.  
  1054. /*
  1055.  * application-defined silent error reporting routine
  1056.  * for Audio File Library
  1057.  */
  1058. static void
  1059. //quietAFerror(long code, const char *desc)
  1060. quietAFerror(long, const char *)
  1061. {
  1062. }
  1063.